package com.cskaoyan.javase.object._6clone.exercise;

/**
 * 深度克隆练习：请完成类FirstLevel的深度克隆。
 * 现在有三个类 FirstLevel 、SecondLevel 、ThirdLevel
 *
 * FirstLevel 类有三个属性：
 *
 * int firstIntValue;
 * double firstDoubleValue;
 * SecondLevel second;
 *
 * SecondLevel 类有三个属性：
 *
 * int secondIntValue;
 * double secondDoubleValue;
 * ThirdLevel third;
 *
 * ThirdLevel 类有两个属性：
 *
 * int thirdIntValue;
 * double thirdDoubleValue;
 *
 *
 * 思考:
 *      String是最典型的引用数据类型
 *      如果类中有String的成员变量
 *      那么需要对它做深度克隆吗?
 *      不需要,而且即便你想做也做不了
 *
 *
 *
 * @since 09:48
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) throws CloneNotSupportedException {
        FirstLevel first = new FirstLevel(10, 20, new SecondLevel(100, 200, new ThirdLevel(1000, 2000,"张三")));
        FirstLevel cloneFirst = first.clone();
        System.out.println();
        first.second.third.name = "李四";
    }
}

class FirstLevel implements Cloneable {
    int firstIntValue;
    double firstDoubleValue;
    SecondLevel second;

    @Override
    protected FirstLevel clone() throws CloneNotSupportedException {
        // a.深度克隆是在浅克隆基础上完成的
        FirstLevel cloneFirst = (FirstLevel) super.clone();
        // b.然后将对象中引用所指向的对象克隆一份
        SecondLevel cloneSecond = second.clone();
        // c.将克隆对象中的克隆引用指向步骤b中克隆对象
        cloneFirst.second = cloneSecond;
        return cloneFirst;
    }

    public FirstLevel(int firstIntValue, double firstDoubleValue, SecondLevel second) {
        this.firstIntValue = firstIntValue;
        this.firstDoubleValue = firstDoubleValue;
        this.second = second;
    }
}

class SecondLevel implements Cloneable {
    int secondIntValue;
    double secondDoubleValue;
    ThirdLevel third;

    @Override
    protected SecondLevel clone() throws CloneNotSupportedException {
        SecondLevel cloneSecond = (SecondLevel) super.clone();
        cloneSecond.third = third.clone();
        return cloneSecond;
    }

    public SecondLevel(int secondIntValue, double secondDoubleValue, ThirdLevel third) {
        this.secondIntValue = secondIntValue;
        this.secondDoubleValue = secondDoubleValue;
        this.third = third;
    }
}

class ThirdLevel implements Cloneable {
    int thirdIntValue;
    double thirdDoubleValue;
    String name;

    @Override
    protected ThirdLevel clone() throws CloneNotSupportedException {
        return (ThirdLevel) super.clone();
    }

    public ThirdLevel(int thirdIntValue, double thirdDoubleValue) {
        this.thirdIntValue = thirdIntValue;
        this.thirdDoubleValue = thirdDoubleValue;
    }

    public ThirdLevel(int thirdIntValue, double thirdDoubleValue, String name) {
        this.thirdIntValue = thirdIntValue;
        this.thirdDoubleValue = thirdDoubleValue;
        this.name = name;
    }
}